package com.ecommerce.dddmodules.infrastructure.db;

import com.ecommerce.dddmodules.ordercontext.model.CustomerOrder;
import com.ecommerce.dddmodules.ordercontext.repository.CustomerOrderRepository;
import com.ecommerce.dddmodules.shippingcontext.model.PackageItem;
import com.ecommerce.dddmodules.shippingcontext.model.ShippableOrder;
import com.ecommerce.dddmodules.shippingcontext.repository.ShippingOrderRepository;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * @packageName: infrastructure.db（基础设施.数据库包）
 * @className: InMemoryOrderStore(内存订单存储)
 * @description: 实现客户订单存储库和发货上下文存储库
 * @author: luds
 * @version: v1.0
 * @date: 2021-04/02
 */
public class InMemoryOrderStore implements CustomerOrderRepository, ShippingOrderRepository {
	/**
	 * 定义一个静态各线程间共享的 内存订单存储单例
	 */
	private volatile static InMemoryOrderStore instance = new InMemoryOrderStore();

	/**
	 * 定义一个模拟的持久化订单存储空间
	 */
	private Map<Integer, PersistenceOrder> ordersDb = new HashMap<>();

	/**
	 * 获取一个静态各线程可共享的单例
	 * @return 返回一个静态各线程可共享的单例
	 */
	public static InMemoryOrderStore provider() {
		return instance;
	}

	/**
	 * 存储客户订单（实现）
	 * @param order 客户订单
	 */
	@Override
	public void saveCustomerOrder(CustomerOrder order) {
		this.ordersDb.put(order.getOrderId(), new PersistenceOrder(order.getOrderId(),
				order.getPaymentMethod(),
				order.getAddress(),
				order
						.getOrderItems()
						.stream()
						.map(orderItem ->
								new PersistenceOrder.OrderItem(orderItem.getProductId(),
										orderItem.getQuantity(),
										orderItem.getUnitWeight(),
										orderItem.getUnitPrice()))
						.collect(Collectors.toList())
		));
	}
	/**
	 * 根据订单ID，查找可发货订单（实现）
	 * @param orderId 客户订单
	 */
	@Override
	public Optional<ShippableOrder> findShippableOrder(int orderId) {
		if (!this.ordersDb.containsKey(orderId)) return Optional.empty();
		PersistenceOrder orderRecord = this.ordersDb.get(orderId);
		return Optional.of(
				new ShippableOrder(orderRecord.orderId, orderRecord.orderItems
						.stream().map(orderItem -> new PackageItem(orderItem.productId,
								orderItem.unitWeight,
								orderItem.quantity * orderItem.unitPrice)
						).collect(Collectors.toList())));
	}
	/**
	 * @packageName: infrastructure.db（基础设施.数据库包）
	 * @className: PersistenceOrder(持久化订单)
	 * @description: 实现客户订单存储库和发货上下文存储库
	 * @author: luds
	 * @version: v1.0
	 * @date: 2021-04/02
	 */
	public static class PersistenceOrder {
		/**
		 * 订单ID
		 */
		public int orderId;
		/**
		 * 付款方式
		 */
		public String paymentMethod;
		/**
		 * 送货地址
		 */
		public String address;
		/**
		 * 订单项目明细
		 */
		public List<OrderItem> orderItems;

		/**
		 * 由订单ID、付款方式、送货地址、订单项目明细构造持久化订单
		 * @param orderId 订单ID
		 * @param paymentMethod 付款方式
		 * @param address 送货地址
		 * @param orderItems 订单项目明细
		 */
		public PersistenceOrder(int orderId, String paymentMethod, String address, List<OrderItem> orderItems) {
			this.orderId = orderId;
			this.paymentMethod = paymentMethod;
			this.address = address;
			this.orderItems = orderItems;
		}

		/**
		 * 内部静态订单项目类
		 */
		public static class OrderItem {
			/**
			 * 产品ID
			 */
			public int productId;
			/**
			 * 单价
			 */
			public float unitPrice;
			/**
			 * 单位重量
			 */
			public float unitWeight;
			/**
			 * 数量
			 */
			public int quantity;

			/**
			 * 由产品ID、数量、单位重量、单价构造订单项目
			 * @param productId 产品ID
			 * @param quantity 数量
			 * @param unitWeight 单位重量
			 * @param unitPrice 单价
			 */
			public OrderItem(int productId, int quantity, float unitWeight, float unitPrice) {
				this.unitWeight = unitWeight;
				this.quantity = quantity;
				this.unitPrice = unitPrice;
				this.productId = productId;
			}
		}
	}
}
